home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * VIRTRSTR.C - implementation of black and white virtual raster device. *
- * *
- * This program implements a virtual raster device of any size up to memory *
- * limit. *
- * *
- * Written by: Gershon Elber IBM PC Ver 1.0, Jan. 1990 *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
-
- #ifdef __MSDOS__
- #include <dos.h>
- #include <alloc.h>
- #else
- char *malloc(unsigned int size);
- #endif /* __MSDOS__ */
-
- #include "virtrstr.h"
-
- #define ABS(x) ((x) > 0 ? (x) : (-(x)))
- #define INT_SWAP(x, y) { int TempI; TempI = x; x = y; y = TempI; }
-
- /* Given an angle and a radius, uses the tables below to map the cos/sin: */
- #define MAP_COS(Angle, Radius) ((int) ((CosTable[Angle] * \
- ((long) Radius) + 16384L) >> 15));
- #define MAP_SIN(Angle, Radius) ((int) ((SinTable[Angle] * \
- ((long) Radius) + 16384L) >> 15));
-
- /* Sines and cosines of integer angles in the range of 0 to 45 degrees, */
- /* multiplied by 32767 (2^15 - 1). */
- static int SinTable[] = {
- 0, 571, 1143, 1714, 2285, 2855, 3425, 3993, 4560, 5125,
- 5689, 6252, 6812, 7370, 7927, 8480, 9031, 9580, 10125, 10667,
- 11206, 11742, 12274, 12803, 13327, 13847, 14364, 14875, 15383, 15885,
- 16383, 16876, 17363, 17846, 18323, 18794, 19259, 19719, 20173, 20620,
- 21062, 21497, 21925, 22347, 22761, 23169
- };
-
- static int CosTable[] = {
- 32767, 32762, 32747, 32722, 32687, 32642, 32587, 32522, 32448, 32363,
- 32269, 32164, 32050, 31927, 31793, 31650, 31497, 31335, 31163, 30981,
- 30790, 30590, 30381, 30162, 29934, 29696, 29450, 29195, 28931, 28658,
- 28377, 28086, 27787, 27480, 27165, 26841, 26509, 26168, 25820, 25464,
- 25100, 24729, 24350, 23964, 23570, 23169
- };
-
- /*****************************************************************************
- * Driver Local Data Variables *
- *****************************************************************************/
- #ifdef __MSDOS__
- static char far **FrameBuffer = NULL; /* Virtual screen is saved here. */
- static char far *AllocBlock = NULL;
- #else
- static char **FrameBuffer = NULL;
- static char *AllocBlock = NULL;
- #endif /* __MSDOS__ */
-
- static int FrameBufferX = 0, FrameBufferY = 0;
- static int BytesPerLine = 0;
-
- static TextOrientationType TextOrientation = TEXT_ORIENT_HORIZ;
- static int TextScale = 1;
- static TextHorizJustifyType TextXCenter = TEXT_X_CENTER;
- static TextVertJustifyType TextYCenter = TEXT_Y_CENTER;
-
- static int CursorX = 0, CursorY = 0; /* Current Cursor position. */
-
- static int CrntColor = 1; /* Default is to DRAW, 0 will ERASE. */
-
- /*****************************************************************************
- * Ascii 8 by 8 regular font - only first 128 characters are supported. *
- *****************************************************************************/
- static unsigned char AsciiTable[][8] = {
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Ascii 0 */
- { 0x3c, 0x42, 0xa5, 0x81, 0xbd, 0x42, 0x3c, 0x00 }, /* Ascii 1 */
- { 0x3c, 0x7e, 0xdb, 0xff, 0xc3, 0x7e, 0x3c, 0x00 }, /* Ascii 2 */
- { 0x00, 0xee, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00 }, /* Ascii 3 */
- { 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00 }, /* Ascii 4 */
- { 0x00, 0x3c, 0x18, 0xff, 0xff, 0x08, 0x18, 0x00 }, /* Ascii 5 */
- { 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x10, 0x38, 0x00 }, /* Ascii 6 */
- { 0x00, 0x00, 0x18, 0x3c, 0x18, 0x00, 0x00, 0x00 }, /* Ascii 7 */
- { 0xff, 0xff, 0xe7, 0xc3, 0xe7, 0xff, 0xff, 0xff }, /* Ascii 8 */
- { 0x00, 0x3c, 0x42, 0x81, 0x81, 0x42, 0x3c, 0x00 }, /* Ascii 9 */
- { 0xff, 0xc3, 0xbd, 0x7e, 0x7e, 0xbd, 0xc3, 0xff }, /* Ascii 10 */
- { 0x1f, 0x07, 0x0d, 0x7c, 0xc6, 0xc6, 0x7c, 0x00 }, /* Ascii 11 */
- { 0x00, 0x7e, 0xc3, 0xc3, 0x7e, 0x18, 0x7e, 0x18 }, /* Ascii 12 */
- { 0x04, 0x06, 0x07, 0x04, 0x04, 0xfc, 0xf8, 0x00 }, /* Ascii 13 */
- { 0x0c, 0x0a, 0x0d, 0x0b, 0xf9, 0xf9, 0x1f, 0x1f }, /* Ascii 14 */
- { 0x00, 0x92, 0x7c, 0x44, 0xc6, 0x7c, 0x92, 0x00 }, /* Ascii 15 */
- { 0x00, 0x00, 0x60, 0x78, 0x7e, 0x78, 0x60, 0x00 }, /* Ascii 16 */
- { 0x00, 0x00, 0x06, 0x1e, 0x7e, 0x1e, 0x06, 0x00 }, /* Ascii 17 */
- { 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18 }, /* Ascii 18 */
- { 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00 }, /* Ascii 19 */
- { 0xff, 0xb6, 0x76, 0x36, 0x36, 0x36, 0x36, 0x00 }, /* Ascii 20 */
- { 0x7e, 0xc1, 0xdc, 0x22, 0x22, 0x1f, 0x83, 0x7e }, /* Ascii 21 */
- { 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00 }, /* Ascii 22 */
- { 0x18, 0x7e, 0x18, 0x18, 0x7e, 0x18, 0x00, 0xff }, /* Ascii 23 */
- { 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00 }, /* Ascii 24 */
- { 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x00 }, /* Ascii 25 */
- { 0x00, 0x04, 0x06, 0xff, 0x06, 0x04, 0x00, 0x00 }, /* Ascii 26 */
- { 0x00, 0x20, 0x60, 0xff, 0x60, 0x20, 0x00, 0x00 }, /* Ascii 27 */
- { 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xff, 0x00 }, /* Ascii 28 */
- { 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00 }, /* Ascii 29 */
- { 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x00, 0x00 }, /* Ascii 30 */
- { 0x00, 0x00, 0x00, 0xfe, 0x7c, 0x38, 0x10, 0x00 }, /* Ascii 31 */
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* */
- { 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x00 }, /* ! */
- { 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* " */
- { 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00 }, /* # */
- { 0x10, 0x7c, 0xd2, 0x7c, 0x86, 0x7c, 0x10, 0x00 }, /* $ */
- { 0xf0, 0x96, 0xfc, 0x18, 0x3e, 0x72, 0xde, 0x00 }, /* % */
- { 0x30, 0x48, 0x30, 0x78, 0xce, 0xcc, 0x78, 0x00 }, /* & */
- { 0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* ' */
- { 0x10, 0x60, 0xc0, 0xc0, 0xc0, 0x60, 0x10, 0x00 }, /* ( */
- { 0x10, 0x0c, 0x06, 0x06, 0x06, 0x0c, 0x10, 0x00 }, /* ) */
- { 0x00, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x00, 0x00 }, /* * */
- { 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00 }, /* + */
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x70 }, /* , */
- { 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00 }, /* - */
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00 }, /* . */
- { 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00 }, /* / */
- { 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00 }, /* 0x */
- { 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x3c, 0x00 }, /* 1 */
- { 0x7c, 0xc6, 0x06, 0x0c, 0x30, 0x60, 0xfe, 0x00 }, /* 2 */
- { 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00 }, /* 3 */
- { 0x0e, 0x1e, 0x36, 0x66, 0xfe, 0x06, 0x06, 0x00 }, /* 4 */
- { 0xfe, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xfc, 0x00 }, /* 5 */
- { 0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00 }, /* 6 */
- { 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x60, 0x00 }, /* 7 */
- { 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00 }, /* 8 */
- { 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00 }, /* 9 */
- { 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00 }, /* : */
- { 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x20, 0x00 }, /* }, */
- { 0x00, 0x1c, 0x30, 0x60, 0x30, 0x1c, 0x00, 0x00 }, /* < */
- { 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00 }, /* = */
- { 0x00, 0x70, 0x18, 0x0c, 0x18, 0x70, 0x00, 0x00 }, /* > */
- { 0x7c, 0xc6, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00 }, /* ? */
- { 0x7c, 0x82, 0x9a, 0xaa, 0xaa, 0x9e, 0x7c, 0x00 }, /* @ */
- { 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00 }, /* A */
- { 0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0x00 }, /* B */
- { 0x7c, 0xc6, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00 }, /* C */
- { 0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00 }, /* D */
- { 0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xfe, 0x00 }, /* E */
- { 0xfe, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0x00 }, /* F */
- { 0x7c, 0xc6, 0xc0, 0xce, 0xc6, 0xc6, 0x7e, 0x00 }, /* G */
- { 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00 }, /* H */
- { 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00 }, /* I */
- { 0x1e, 0x06, 0x06, 0x06, 0xc6, 0xc6, 0x7c, 0x00 }, /* J */
- { 0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0xc6, 0x00 }, /* K */
- { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x00 }, /* L */
- { 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0x00 }, /* M */
- { 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00 }, /* N */
- { 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00 }, /* O */
- { 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0x00 }, /* P */
- { 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x06 }, /* Q */
- { 0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xc6, 0x00 }, /* R */
- { 0x78, 0xcc, 0x60, 0x30, 0x18, 0xcc, 0x78, 0x00 }, /* S */
- { 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00 }, /* T */
- { 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00 }, /* U */
- { 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00 }, /* V */
- { 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00 }, /* W */
- { 0xc6, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0xc6, 0x00 }, /* X */
- { 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x00 }, /* Y */
- { 0xfe, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xfe, 0x00 }, /* Z */
- { 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00 }, /* [ */
- { 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x00 }, /* \ */
- { 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00 }, /* ] */
- { 0x00, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00 }, /* ^ */
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff }, /* _ */
- { 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* ` */
- { 0x00, 0x00, 0x7c, 0x06, 0x7e, 0xc6, 0x7e, 0x00 }, /* a */
- { 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0x00 }, /* b */
- { 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0x7e, 0x00 }, /* c */
- { 0x06, 0x06, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x00 }, /* d */
- { 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7e, 0x00 }, /* e */
- { 0x1e, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x30, 0x00 }, /* f */
- { 0x00, 0x00, 0x7e, 0xc6, 0xce, 0x76, 0x06, 0x7c }, /* g */
- { 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00 }, /* */
- { 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00 }, /* i */
- { 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0xf0 }, /* j */
- { 0xc0, 0xc0, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0x00 }, /* k */
- { 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00 }, /* l */
- { 0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xc6, 0xc6, 0x00 }, /* m */
- { 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x00 }, /* n */
- { 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00 }, /* o */
- { 0x00, 0x00, 0xfc, 0xc6, 0xc6, 0xe6, 0xdc, 0xc0 }, /* p */
- { 0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xce, 0x76, 0x06 }, /* q */
- { 0x00, 0x00, 0x6e, 0x70, 0x60, 0x60, 0x60, 0x00 }, /* r */
- { 0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0xfc, 0x00 }, /* s */
- { 0x30, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x1c, 0x00 }, /* t */
- { 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x00 }, /* u */
- { 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00 }, /* v */
- { 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0x6c, 0x00 }, /* w */
- { 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00 }, /* x */
- { 0x00, 0x00, 0xc6, 0xc6, 0xce, 0x76, 0x06, 0x7c }, /* y */
- { 0x00, 0x00, 0xfc, 0x18, 0x30, 0x60, 0xfc, 0x00 }, /* z */
- { 0x0e, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0e, 0x00 }, /* { */
- { 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00 }, /* | */
- { 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00 }, /* } */
- { 0x00, 0x00, 0x70, 0x9a, 0x0e, 0x00, 0x00, 0x00 }, /* ~ */
- { 0x00, 0x00, 0x18, 0x3c, 0x66, 0xff, 0x00, 0x00 } /* Ascii 127 */
- };
-
- static void VirtArcAux(int XCenter, int YCenter, int Radius, int Octant,
- int StartAngle, int EndAngle);
- static void VirtArcAuxX(int XCenter, int YCenter, int Radius,
- int XStart, int YStart, int XEnd, int YEnd);
- static void VirtArcAuxY(int XCenter, int YCenter, int Radius,
- int XStart, int YStart, int XEnd, int YEnd);
-
- /*****************************************************************************
- * Virtual driver init routine - allocate memory and clear it. If allocation *
- * is succesful return TRUE, FALSE otherwise. *
- *****************************************************************************/
- int VirtInit(int x, int y)
- {
- int LineOffset, Segment, i;
-
- FrameBufferX = x;
- FrameBufferY = ((y + 7) >> 3) << 3 ;
-
- /* The offset from one line to next in paragraphs: first convert to */
- /* bytes by dividing by 8 and then to paragraphs by dividing by 16. */
- /* Finally fix the offset if division clipped off remainder... */
- LineOffset = FrameBufferY >> 7;
- while ((LineOffset << 7) < FrameBufferY)
- LineOffset++;
- BytesPerLine = LineOffset << 4; /* So how many bytes per line we have? */
-
- /* Allocate a block of FrameBufferX pointer (for each line) and one big */
- /* block for the whole frame buffer, which will be split to lines. */
- #ifdef __MSDOS__
- if ((FrameBuffer = (char far **) farmalloc(FrameBufferX *
- sizeof(char far *))) == NULL)
- return FALSE;
- if ((AllocBlock = farmalloc(((long) FrameBufferX) *
- ((long) LineOffset) * 16)) == NULL)
- {
- farfree((char far *) FrameBuffer);
- return FALSE;
- }
- #else
- if ((FrameBuffer = (char **) malloc(FrameBufferX *
- sizeof(char *))) == NULL)
- return FALSE;
- if ((AllocBlock = (char *) malloc(FrameBufferX * BytesPerLine)) == NULL)
- {
- free((char *) FrameBuffer);
- return FALSE;
- }
- #endif /* __MSDOS__ */
-
- /* The allocated block is split here to lines so we can access the */
- /* screen faster, and mainly easier. */
- #ifdef __MSDOS__
- Segment = FP_SEG(AllocBlock);
-
- for (i = 0; i < FrameBufferX; i++)
- FrameBuffer[i] = MK_FP(Segment + LineOffset * i, 0x0008);
- #else
- for (i = 0; i < FrameBufferX; i++)
- FrameBuffer[i] = AllocBlock + BytesPerLine * i;
- #endif /* __MSDOS__ */
-
- VirtClear();
- return TRUE;
- }
-
- /*****************************************************************************
- * Clear all bytes in the virtual raster array to zero. *
- *****************************************************************************/
- void VirtClear(void)
- {
- int i;
-
- for (i = 0; i < FrameBufferX; i++)
- memset(FrameBuffer[i], 0, BytesPerLine);
- }
-
- /*****************************************************************************
- * Free memory allocated. *
- *****************************************************************************/
- void VirtClose(void)
- {
- #ifdef __MSDOS__
- farfree(AllocBlock);
- farfree((char far **) FrameBuffer);
- #else
- free((char *) AllocBlock);
- free((char *) FrameBuffer);
- #endif /* __MSDOS__ */
-
- FrameBuffer = NULL;
- }
-
- /*****************************************************************************
- * Set Cursor current position. *
- *****************************************************************************/
- void VirtMoveTo(int x, int y)
- {
- CursorX = x;
- CursorY = y;
- }
-
- /*****************************************************************************
- * Set Cursor current position. *
- *****************************************************************************/
- void VirtMoveRelTo(int x, int y)
- {
- CursorX += x;
- CursorY += y;
- }
-
- /*****************************************************************************
- * Draw line from current Cursor position to the given point. *
- * Note the Cursor position is updated to the given point. *
- *****************************************************************************/
- void VirtLineTo(int x, int y)
- {
- VirtLine(CursorX, CursorY, x, y);
-
- CursorX = x;
- CursorY = y;
- }
-
- /*****************************************************************************
- * Draw line from current Cursor position to the given relative point. *
- * Note the Cursor position is updated to the given point. *
- *****************************************************************************/
- void VirtLineRelTo(int x, int y)
- {
- VirtLine(CursorX, CursorY, CursorX + x, CursorY + y);
-
- CursorX += x;
- CursorY += y;
- }
-
- /*****************************************************************************
- * Draw a line between the two given points. *
- * Note the Cursor position is NOT updated in this routine. *
- * Implement a simple DDA between the two points. *
- *****************************************************************************/
- void VirtLine(int x1, int y1, int x2, int y2)
- {
- int Accumulate,
- x = x1,
- y = y1,
- Dx = ABS(x1 - x2),
- Dy = ABS(y1 - y2),
- XStep = x2 > x1 ? 1 : -1,
- YStep = y2 > y1 ? 1 : -1;
-
- VirtSetPixel(x, y);
-
- if (Dx > Dy) {
- /* Dx is modified by 1 in each step. */
- Accumulate = Dx / 2;
- do {
- Accumulate -= Dy;
- if (Accumulate < 0) {
- y += YStep;
- Accumulate += Dx;
- }
- x += XStep;
- VirtSetPixel(x, y);
- }
- while (x != x2);
- }
- else {
- /* Dy is modified by 1 in each step. */
- Accumulate = Dy / 2;
- do {
- Accumulate -= Dx;
- if (Accumulate < 0) {
- x += XStep;
- Accumulate += Dy;
- }
- y += YStep;
- VirtSetPixel(x, y);
- }
- while (y != y2);
- }
- }
-
- /*****************************************************************************
- * Draw a filled box. *
- *****************************************************************************/
- void VirtBar(int x1, int y1, int x2, int y2)
- {
- int i;
-
- if (x1 < x2)
- for (i = x1; i <= x2; i++)
- VirtLine(i, y1, i, y2);
- else
- for (i = x2; i <= x1; i++)
- VirtLine(i, y1, i, y2);
- }
-
- /*****************************************************************************
- * Draw a circle, given the center and the radius. *
- *****************************************************************************/
- void VirtCirc(int x, int y, int r)
- {
- int i;
-
- for (i=0; i<8; i++)
- VirtArcAux(x, y, r, i, 0, 45);
- }
-
- /*****************************************************************************
- * Draw an arc, given the center, radius, and angles. *
- * Note arc are supported to 45 degrees boundaries only, and rounded otherwise*
- *****************************************************************************/
- void VirtArc(int x, int y, int r, int Angle1, int Angle2)
- {
- int Angle, Angle1Mod, Angle2Mod;
-
- if (Angle1 > Angle2) {
- Angle = Angle1;
- Angle1 = Angle2;
- Angle2 = Angle;
- }
-
- Angle1Mod = Angle1 % 45;
- Angle2Mod = Angle2 % 45;
- Angle1 = Angle1 / 45;
- Angle2 = Angle2 / 45;
-
- while (Angle1 < 0) Angle1 += 8;
- while (Angle2 < 0) Angle2 += 8;
- while (Angle1 >= 8) Angle1 -= 8;
- while (Angle2 >= 16) Angle2 -= 8;
-
- while (Angle1 < Angle2) {
- VirtArcAux(x, y, r, Angle1++ % 8, Angle1Mod, 45);
- Angle1Mod = 0;
- }
- if (Angle2Mod > 0) VirtArcAux(x, y, r, Angle2 % 8, 0, Angle2Mod);
-
- }
-
- /*****************************************************************************
- * Draw an arc, given the center, radius, and angles. *
- * This aux routine draw on one octant as specified by Octant (0..7). *
- * StartAngle and EndAngles are in [0..45] and are relative to Octant base. *
- *****************************************************************************/
- static void VirtArcAux(int XCenter, int YCenter, int Radius, int Octant,
- int StartAngle, int EndAngle)
- {
- int XStart, YStart, XEnd, YEnd;
- switch (Octant) {
- case 0:
- XStart = MAP_COS(StartAngle, Radius);
- YStart = MAP_SIN(StartAngle, Radius);
- XEnd = MAP_COS(EndAngle, Radius);
- YEnd = MAP_SIN(EndAngle, Radius);
- break;
- case 1:
- XStart = MAP_SIN(45 - EndAngle, Radius);
- YStart = MAP_COS(45 - EndAngle, Radius);
- XEnd = MAP_SIN(45 - StartAngle, Radius);
- YEnd = MAP_COS(45 - StartAngle, Radius);
- break;
- case 2:
- XStart = -MAP_SIN(StartAngle, Radius);
- YStart = MAP_COS(StartAngle, Radius);
- XEnd = -MAP_SIN(EndAngle, Radius);
- YEnd = MAP_COS(EndAngle, Radius);
- break;
- case 3:
- XStart = -MAP_COS(45 - EndAngle, Radius);
- YStart = MAP_SIN(45 - EndAngle, Radius);
- XEnd = -MAP_COS(45 - StartAngle, Radius);
- YEnd = MAP_SIN(45 - StartAngle, Radius);
- break;
- case 4:
- XStart = -MAP_COS(StartAngle, Radius);
- YStart = -MAP_SIN(StartAngle, Radius);
- XEnd = -MAP_COS(EndAngle, Radius);
- YEnd = -MAP_SIN(EndAngle, Radius);
- break;
- case 5:
- XStart = -MAP_SIN(45 - EndAngle, Radius);
- YStart = -MAP_COS(45 - EndAngle, Radius);
- XEnd = -MAP_SIN(45 - StartAngle, Radius);
- YEnd = -MAP_COS(45 - StartAngle, Radius);
- break;
- case 6:
- XStart = MAP_SIN(StartAngle, Radius);
- YStart = -MAP_COS(StartAngle, Radius);
- XEnd = MAP_SIN(EndAngle, Radius);
- YEnd = -MAP_COS(EndAngle, Radius);
- break;
- case 7:
- XStart = MAP_COS(45 - EndAngle, Radius);
- YStart = -MAP_SIN(45 - EndAngle, Radius);
- XEnd = MAP_COS(45 - StartAngle, Radius);
- YEnd = -MAP_SIN(45 - StartAngle, Radius);
- break;
- }
-
- if (Octant == 0 || Octant == 3 || Octant == 4 || Octant == 7)
- VirtArcAuxX(XCenter, YCenter, Radius, XStart, YStart, XEnd, YEnd);
- else
- VirtArcAuxY(XCenter, YCenter, Radius, XStart, YStart, XEnd, YEnd);
- }
-
- /*****************************************************************************
- * Draw an arc, given the center, radius, XStart, YStart and XEnd, YEnd. *
- * X/YStart and X/YEnd are given relative to a circle centered at the origin. *
- * This aux routine draw one arc in upto one octant (45 degrees at most), *
- * in which ABS(Y) <= ABS(X). *
- * See Foley and Van Dam, pp 445, for basic idea. *
- *****************************************************************************/
- static void VirtArcAuxX(int XCenter, int YCenter, int Radius,
- int XStart, int YStart, int XEnd, int YEnd)
- {
- int d = 3 - (Radius << 1),
- x = XStart, y = YStart,
- XStep = XStart < 0 ? 1 : -1,
- YStep = YEnd > 0 ? 1 : -1;
-
- while (ABS(x) >= ABS(XEnd)) {
- VirtSetPixel(XCenter + x, YCenter + y);
- if (d < 0)
- d += (ABS(y) << 2) + 6;
- else {
- d += ((ABS(y) - ABS(x)) << 2) + 10;
- x += XStep;
- }
- y += YStep;
- }
- }
-
- /*****************************************************************************
- * Draw an arc, given the center, radius, XStart, YStart and XEnd, YEnd. *
- * X/YStart and X/YEnd are given relative to a circle centered at the origin. *
- * This aux routine draw one arc in upto one octant (45 degrees at most), *
- * in which ABS(Y) >= ABS(X). *
- * See Foley and Van Dam, pp 445, for basic idea. *
- *****************************************************************************/
- static void VirtArcAuxY(int XCenter, int YCenter, int Radius,
- int XStart, int YStart, int XEnd, int YEnd)
- {
- int d = 3 - (Radius << 1),
- x = XStart, y = YStart,
- XStep = XEnd > 0 ? 1 : -1,
- YStep = YStart < 0 ? 1 : -1;
-
- while (ABS(y) >= ABS(YEnd)) {
- VirtSetPixel(XCenter + x, YCenter + y);
- if (d < 0)
- d += (ABS(x) << 2) + 6;
- else {
- d += ((ABS(x) - ABS(y)) << 2) + 10;
- y += YStep;
- }
- x += XStep;
- }
- }
-
- /*****************************************************************************
- * Set current Color to be used in drawing. *
- *****************************************************************************/
- void VirtSetColor(int Color)
- {
- if (Color > 1) return;
- CrntColor = Color;
- }
-
- /*****************************************************************************
- * Set text format to be drawn - orientation (horizontal/vertical) and *
- * centering around the Cursor position in X and Y axes. *
- *****************************************************************************/
- void VirtTextFormat(TextOrientationType Orient, int Scale,
- TextHorizJustifyType XCenter, TextVertJustifyType YCenter)
- {
- TextOrientation = Orient;
- TextScale = Scale;
- TextXCenter = XCenter;
- TextYCenter = YCenter;
- }
-
- /*****************************************************************************
- * Draw the given NULL terminated text in the current Cursor position and *
- * with the format as specified by VirtTextFormat. *
- *****************************************************************************/
- void VirtText(char *Str)
- {
- char c, Byte;
- int i, j, k, s, Mask, CharPosX, CharPosY, Len = strlen(Str);
-
- switch (TextOrientation) {
- case TEXT_ORIENT_HORIZ:
- switch (TextXCenter) {
- case TEXT_X_LEFT:
- CharPosX = CursorX;
- break;
- case TEXT_X_CENTER:
- /* Half string width == Len * 4 * TextScale pixels. */
- CharPosX = CursorX - Len * 4 * TextScale;
- break;
- case TEXT_X_RIGHT:
- /* Full string width == Len * 8 * TextScale pixels. */
- CharPosX = CursorX - Len * 8 * TextScale;
- break;
- }
- switch (TextYCenter) {
- case TEXT_Y_TOP:
- CharPosY = CursorY;
- break;
- case TEXT_Y_CENTER:
- CharPosY = CursorY - 4 * TextScale;
- break;
- case TEXT_Y_BOTTOM:
- CharPosY = CursorY - 8 * TextScale;
- break;
- }
- for (i = 0; i < Len; i++, CharPosX += 8 * TextScale) {
- c = Str[i];
- for (j = 0; j < 8 * TextScale; j++) {
- Byte = AsciiTable[c][j / TextScale];
- for (k = 0, Mask = 128; k < 8; k++, Mask >>= 1)
- if (Byte & Mask)
- for (s = TextScale - 1; s >= 0; s--)
- VirtSetPixel(CharPosX + k * TextScale + s,
- CharPosY + j);
- }
- }
- break;
- case TEXT_ORIENT_VERT:
- switch (TextXCenter) {
- case TEXT_X_LEFT:
- CharPosX = CursorX;
- break;
- case TEXT_X_CENTER:
- CharPosX = CursorX - 4 * TextScale;
- break;
- case TEXT_X_RIGHT:
- CharPosX = CursorX - 8 * TextScale;
- break;
- }
- switch (TextYCenter) {
- case TEXT_Y_TOP:
- CharPosY = CursorY;
- break;
- case TEXT_Y_CENTER:
- /* Half string width == Len * 4 * TextScale pixels. */
- CharPosY = CursorY - Len * 4 * TextScale;
- break;
- case TEXT_Y_BOTTOM:
- /* Full string height == Len * 8 * TextScale pixels. */
- CharPosY = CursorY - Len * 8 * TextScale;
- break;
- }
- for (i = 0; i < Len; i++, CharPosY += 8 * TextScale) {
- c = Str[Len - i - 1];
- for (j = 0; j < 8 * TextScale; j++) {
- Byte = AsciiTable[c][j / TextScale];
- for (k = 0, Mask = 1; k < 8; k++, Mask <<= 1)
- if (Byte & Mask)
- for (s = TextScale - 1; s >= 0; s--)
- VirtSetPixel(CharPosX + j,
- CharPosY + k * TextScale + s);
- }
- }
- break;
- }
- }
-
- /****************************************************************************
- * Routine to return text width in pixels. *
- ****************************************************************************/
- int VirtTextWidth(char *Str)
- {
- return strlen(Str) * 8 * TextScale;
- }
-
- /****************************************************************************
- * Routine to return text height in pixels. *
- ****************************************************************************/
- int VirtTextHeight(char *Str)
- {
- return 8 * TextScale;
- }
-
- /*****************************************************************************
- * Get the value of the pixel at the given XY location. *
- *****************************************************************************/
- int VirtGetPixel(int x, int y)
- {
- if (x >= FrameBufferX || y >= FrameBufferY)
- return 0;
- else
- return FrameBuffer[x][y >> 3] & (1 << (y & 0x07)) ? 1 : 0;
- }
-
- /*****************************************************************************
- * Get the value of the pixel at the given XY location, to the CrntColor. *
- *****************************************************************************/
- void VirtSetPixel(int x, int y)
- {
- if (x <= 0 || y <= 0 || x >= FrameBufferX || y >= FrameBufferY) return;
-
- switch (CrntColor) {
- case 0:
- FrameBuffer[x][y >> 3] &= ~(CrntColor << (y & 0x07));
- break;
- case 1:
- FrameBuffer[x][y >> 3] |= (CrntColor << (y & 0x07));
- break;
- }
- }
-
- /*****************************************************************************
- * Get a block of pixels from the virtual raster device, into Buffer. *
- *****************************************************************************/
- void VirtGetBlock(int x1, int y1, int x2, int y2, char *Buffer)
- {
- int i, j, k, Count, Data, Bit;
-
- if (x1 > x2) {
- i = x1;
- x1 = x2;
- x2 = i;
- }
- if (y1 > y2) {
- i = y1;
- y1 = y2;
- y2 = i;
- }
-
- k = Data = Count = 0;
- for (i = x1; i <= x2; i++)
- for (j = y1; j <= y2; j++) {
- Bit = VirtGetPixel(i, j);
- Data = (Data << 1) + Bit;
- if (++Count == 8) {
- Buffer[k++] = Data;
- Data = Count = 0;
- }
- }
-
- if (Count != 0) {
- Data <<= (8 - Count);
- Buffer[k++] = Data;
- }
- }
-